package net.zkbc.helloworld.service.impl;

import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import net.zkbc.helloworld.entity.User;
import net.zkbc.helloworld.repository.UserRepository;
import net.zkbc.helloworld.repository.UserRepository.DelegatingUserSpecificationExecutor;
import net.zkbc.helloworld.service.UserService;
import net.zkbc.helloworld.util.ParameterException;
import net.zkbc.helloworld.util.Validators;
import net.zkbc.shiro.service.AbstractShiroUserService;

@Component
public class UserServiceImpl extends AbstractShiroUserService implements UserService {

	@Autowired
	private UserRepository userRepos;

	@Override
	public List<User> findAllUsers(User filter) {
		DelegatingUserSpecificationExecutor executor = new DelegatingUserSpecificationExecutor(userRepos);
		return executor.findAll(filter);
	}

	@Transactional(readOnly = true)
	@Override
	public User findUserByLoginName(String loginName) {
		if (StringUtils.isEmpty(loginName)) {
			return null;
		}

		return userRepos.findByLoginName(loginName);
	}

	@Transactional
	@Override
	public User saveUser(User user) {
		encodePassword(user);
		return userRepos.save(user);
	}

	@Transactional
	@Override
	public User changeLoginPassword(String loginName, String plainPassword) {
		User user = findUserByLoginName(loginName);
		if (user == null) {
			return null;
		}

		user.setPlainPassword(plainPassword);
		encodePassword(user);
		userRepos.updateLoginPassword(user);

		return user;
	}

	@Transactional
	@Override
	public void changeMyLoginPassword(String plainOldPassword, String plainNewPassword) {
		User user = (User) getLoginUser();
		String oldPassword = encodePassword(plainOldPassword, getSaltBytes(user));
		if (!user.getPassword().equals(oldPassword)) {
			throw new ParameterException(Validators.CODE_PWD_ERROR);
		}
		changeLoginPassword(user.getLoginName(), plainNewPassword);
	}

	private void encodePassword(User user) {
		if (StringUtils.isEmpty(user.getPlainPassword())) {
			return;
		}

		user.setLoginPasswordTime(new Date());
		user.setSalt(getSalt());
		user.setPassword(encodePassword(user.getPlainPassword(), getSaltBytes(user)));
	}

}
